﻿package game.socket {
	import flash.utils.ByteArray;
	
	public class SocketPackage {
		
		public function SocketPackage():void {
			
		}
		
		public static function createParse(ba:ByteArray):Vector.<SocketData> {
			var data:Vector.<SocketData> = new Vector.<SocketData>;
			while (ba.bytesAvailable>4) {
				var type:int = ba.readByte();
				switch (type) {
					case SocketData.BYTE:		data.push(new SocketData(SocketData.BYTE,	ba.readByte()));	break;
					case SocketData.SHORT:		data.push(new SocketData(SocketData.SHORT,	ba.readShort()));	break;
					case SocketData.INT:		data.push(new SocketData(SocketData.INT,	ba.readInt()));		break;
					case SocketData.STRING:		var len:int = ba.readShort(); data.push(new SocketData(SocketData.INT,	ba.readMultiByte(len, SocketConfig.CHARSET)));	break;
					case SocketData.FLOAT:		data.push(new SocketData(SocketData.FLOAT,	ba.readFloat()));	break;
				}
			}
			return data;
		}
		
		public static function createWrite(data:Vector.<SocketData>, id:int):ByteArray {
			var ba:ByteArray = new ByteArray;
			ba.endian = SocketConfig.ENDIAN;
			ba.writeShort(id);
			ba.writeShort(getLength(data));
			for each (var d:SocketData in data) {
				switch (d.type) {
					case SocketData.BYTE:		ba.writeByte(SocketData.BYTE);		ba.writeByte	(d.value);	break;
					case SocketData.SHORT:		ba.writeByte(SocketData.SHORT);		ba.writeShort	(d.value);	break;
					case SocketData.INT:		ba.writeByte(SocketData.INT);		ba.writeInt		(d.value);	break;
					case SocketData.STRING:		ba.writeByte(SocketData.STRING);	ba.writeShort(d.length); ba.writeMultiByte	(d.value, SocketConfig.CHARSET);	break;
					case SocketData.FLOAT:		ba.writeByte(SocketData.FLOAT);		ba.writeFloat	(d.value); 	break;
					
				}
			}
			ba.writeInt(getHash(ba));
			return ba;
		}
		
		//считает всю длину пакета (без id, length);
		public static function getLength(data:Vector.<SocketData>):int {
			var l:int = 0;
			for each (var d:SocketData in data) {
				l += d.length;
				switch (d.type) {
					case SocketData.BYTE:		l += 1;	break;
					case SocketData.SHORT:		l += 1;	break;
					case SocketData.INT:		l += 1;	break;
					case SocketData.STRING:		l += 3;	break;
					case SocketData.FLOAT:		l += 1;	break;
				}
			}
			return l+8;
		}
		
		//считает хэш пакета
		public static function getHash(ba:ByteArray):int {
			var sum:int = 0;
			for (var i:int = 0; i<ba.length; i++) {
				ba.position = i;
				sum += ba.readUnsignedByte();
			}
			return sum^SocketConfig.HASH;
		}
		
		
	}
	
}